/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
using MyPhotoIndex.Utilities;
using System.Drawing;
using MyPhotoIndex.Interfaces;
using MyPhotoIndex.Settings;
using System.ComponentModel;
using System.Reflection;
using MyPhotoIndex.Utilities.Types;
using MyPhotoIndex.Plugins;

namespace MyPhotoIndex
{
    [Serializable]
    public class DynamicConfiguration : ISettingsManager, IXmlSerializable
    {
        const String USERCONFIGFILENAME = "userSettings.config";

        [NonSerialized]
        private static DynamicConfiguration m_instance;
        [NonSerialized]
        private Dictionary<Type, IDynamicSetting> m_propertyValues;

        public DynamicConfiguration()
        {
            m_propertyValues = new Dictionary<Type, IDynamicSetting>();
        }

        public static DynamicConfiguration Default
        {
            get
            {
                if (m_instance == null)
                {
                    lock (typeof(DynamicConfiguration))
                    {
                        if (m_instance == null)
                        {
                            m_instance = LoadConfiguration();
                        }
                    }
                }
                
                return m_instance;
            }
        }

        private static DynamicConfiguration LoadConfiguration()
        {
            String fileLocation = ConfigurationFilePath;

            try
            {
                using (StreamReader reader = new StreamReader(fileLocation))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(DynamicConfiguration));
                    object config = serializer.Deserialize(reader);
                    m_instance = (DynamicConfiguration)config;
                }
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
                m_instance = new DynamicConfiguration();
            }

            return m_instance;
        }

        public void Save()
        {
            String fileLocation = ConfigurationFilePath;

            try
            {
                using (StreamWriter writer = new StreamWriter(fileLocation))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(DynamicConfiguration));
                    serializer.Serialize(writer, this);
                }
            }
            catch (Exception ex)
            {
                String msg = ex.Message;
            }
        }

        public static String ConfigurationFilePath
        {
            get
            {
                return Path.Combine(ApplicationFolders.DefaultConfigurationPath, USERCONFIGFILENAME);
            }
        }

        [XmlIgnore]
        public IDynamicSetting[] Settings
        {
            get
            {
                IDynamicSetting[] array = new IDynamicSetting[m_propertyValues.Values.Count];
                m_propertyValues.Values.CopyTo(array, 0);

                return array;
            }
        }

        [XmlIgnore]
        public IDynamicSetting this[Type key]
        {
            get
            {
                if (m_propertyValues.ContainsKey(key) == false)
                {
                    Assembly assembly = Assembly.GetAssembly(key);
                    IDynamicSetting setting = (IDynamicSetting)assembly.CreateInstance(key.FullName);
                    m_propertyValues.Add(key, setting);

                    return setting;
                }

                return m_propertyValues[key];
            }
        }

        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            m_propertyValues = new Dictionary<Type, IDynamicSetting>();
            String settingsTypeName = String.Empty;
            while (reader.EOF == false)
            {
                settingsTypeName = reader.Name;

                Type settingType = TypeFinder.FindType(Assembly.GetExecutingAssembly(), settingsTypeName);
                if (settingType == null)
                {
                    try
                    {
                        settingType = Manager.GetType(settingsTypeName);
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(ex);
                    }
                }

                if (settingType != null &&
                    reader.Name.CompareTo(GetType().Name) != 0)
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(settingType);
                        IDynamicSetting o = (IDynamicSetting)serializer.Deserialize(reader);
                        m_propertyValues.Add(settingType, o);
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(ex);
                    }
                }
                else
                {
                    reader.Read();
                }

                if (reader.Name.CompareTo(GetType().Name) == 0)
                {
                    break;
                }
            }
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            foreach (IDynamicSetting setting in m_propertyValues.Values)
            {
                XmlSerializer serializer = new XmlSerializer(setting.GetType());
                serializer.Serialize(writer, setting);
            }
        }

        #endregion
    }
}